/*
 * Copyright (c) 2015. For Intelligent Group.
 */

package com.intelligent.ispc.aop;

import com.intelligent.ispc.common.utils.ApplicationException;
import com.intelligent.ispc.common.utils.ApplicationUtil;
import com.intelligent.ispc.core.dto.DataDictionaryDto;
import com.intelligent.ispc.core.dto.LogDto;
import com.intelligent.ispc.core.dto.RoleDto;
import com.intelligent.ispc.core.dto.UserDto;
import com.intelligent.ispc.core.entity.*;
import com.intelligent.ispc.core.repository.jpa.*;
import com.intelligent.ispc.core.service.LogService;
import com.intelligent.ispc.core.service.SecurityService;
import com.intelligent.ispc.foundation.mail.EmailStatus;
import com.intelligent.ispc.foundation.mail.MailConfiguration;
import com.intelligent.ispc.utils.LogUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.lang.reflect.Method;
import java.util.Date;
import java.util.List;

/**
 * Created by Peter on 2016/3/30.
 */
@Aspect
public class LogAspect {
    private static Logger logger = LoggerFactory.getLogger(LogAspect.class);

    @Autowired
    private LogService logService;

    @Autowired
    private SecurityService securityService;

    @Autowired
    private UserDao userDao;

    @Autowired
    private RoleDao roleDao;

    @Autowired
    private ProjectDao projectDao;

    @Autowired
    private PermissionDao permissionDao;

    @Autowired
    private EmailDao emailDao;

    @Autowired
    private DataDictionaryDao dataDictionaryDao;

    @Autowired
    private TestFileDao testFileDao;


    @Pointcut("execution(* com.intelligent.ispc.core.service.impl.UserServiceImpl.saveUser(..))")
    public void saveUserCall() {
    }

    @Pointcut("execution(* com.intelligent.ispc.core.service.impl.UserServiceImpl.updateUser(..))")
    public void updateUserCall() {
    }

    @Pointcut("execution(* com.intelligent.ispc.core.service.impl.UserServiceImpl.deleteUser(..))")
    public void deleteUserCall() {
    }

    @Pointcut("execution(* com.intelligent.ispc.core.service.impl.UserServiceImpl.resetPassword(..))")
    public void resetPasswordCall() {
    }


    @Pointcut("execution(* com.intelligent.ispc.core.service.impl.RoleServiceImpl.saveRole(..))")
    public void saveRoleCall() {
    }

    @Pointcut("execution(* com.intelligent.ispc.core.service.impl.RoleServiceImpl.updateRole(..))")
    public void updateRoleCall() {
    }

    @Pointcut("execution(* com.intelligent.ispc.core.service.impl.RoleServiceImpl.deleteRole(..))")
    public void deleteRoleCall() {
    }


    @Pointcut("execution(* com.intelligent.ispc.core.service.impl.PermissonServiceImpl.assignRolesForPermission(..))")
    public void assignRolesForPermissionCall() {
    }

    @Pointcut("execution(* com.intelligent.ispc.core.service.impl.PermissonServiceImpl.deleteRoleForPermission(..))")
    public void deleteRoleForPermissionCall() {
    }

    @Pointcut("execution(* com.intelligent.ispc.core.service.impl.UserServiceImpl.assignRolesForUser(..))")
    public void assignRolesForUserCall() {
    }

    /**
     */
    @Pointcut("execution(* com.intelligent.ispc.core.service.impl.UserServiceImpl.deleteRolesForUser(..))")
    public void deleteRolesForUserCall() {
    }

    /**
     */
   /* @Pointcut("execution(* com.intelligent.ispc.core.service.impl.DataIOServiceImpl.importDataFromCvs(..))")
    public void importDataFromCvsCall() {
    }*/

    @Pointcut("execution(* com.intelligent.ispc.core.service.impl.TestFileServiceImpl.logicDeleteTestFile(..))")
    public void logicDeleteTestFileCall() {
    }

    @Pointcut("execution(* com.intelligent.ispc.core.service.impl.TestFileServiceImpl.deleteTestFile(..))")
    public void deleteTestFileCall() {
    }

    @Pointcut("execution(* com.intelligent.ispc.core.service.impl.TestFileServiceImpl.restoreTestFile(..))")
    public void restoreTestFileCall() {
    }

    /**
     */
    @Pointcut("execution(* com.intelligent.ispc.core.service.impl.EmailServiceImpl.saveEmail(..))")
    public void saveEmailCall() {
    }

    @Pointcut("execution(* com.intelligent.ispc.core.service.impl.EmailServiceImpl.updateEmail(..))")
    public void updateEmailCall() {
    }

    @Pointcut("execution(* com.intelligent.ispc.core.service.impl.EmailServiceImpl.deleteEmail(..))")
    public void deleteEmailCall() {
    }

    @Pointcut("execution(* com.intelligent.ispc.core.service.impl.EmailServiceImpl.updateEmailStatus(..))")
    public void updateEmailStatusCall() {
    }


    @Pointcut("execution(* com.intelligent.ispc.core.service.impl.AlarmServiceImpl.updateSystemAlarmRuleCPWR(..))")
    public void updateSystemAlarmRuleCPWRCall() {
    }

    @Pointcut("execution(* com.intelligent.ispc.core.service.impl.AlarmServiceImpl.updateSystemAlarmRuleCCWR(..))")
    public void updateSystemAlarmRuleCCWR() {
    }


    @Around(value = "saveUserCall()")
    public Object saveUserService(ProceedingJoinPoint joinPoint) throws Throwable {
        String userLoginName = securityService.getCurrentUserLoginName();

        if (userLoginName == null || joinPoint.getArgs() == null) {
            return null;
        }

        Object result = null;
        LogDto logDto = new LogDto();
        UserDto dto = (UserDto) joinPoint.getArgs()[0];
        logDto.setCreateBy(userLoginName);
        logDto.setCreateTime(new Date());
        logDto.setOperation(LogUtil.INSERT.getCode());
        StringBuffer msg = new StringBuffer().append(getLogCell(ApplicationModule.MODULE_SYSTEM));
        msg.append(getLogCell("New User"));

        if (dto != null) {
            msg.append(getLogCell(",", "LoginName: " + dto.getLoginName(), "Name: " + dto.getName()));
            logDto.setContent(msg.toString());
        }

        try {
            result = joinPoint.proceed();
            logDto.setResult(LogUtil.SUCCESS.getCode());
        } catch (Exception ex) {
            logDto.setResult(LogUtil.FAILURE.getCode());
            throw new ApplicationException(ex.getMessage());
        } finally {
            logService.log(logDto);
        }

        return result;
    }

    @Around(value = "updateUserCall()")
    public Object updateUserService(ProceedingJoinPoint joinPoint) throws Throwable {
        String userLoginName = securityService.getCurrentUserLoginName();

        if (userLoginName == null || joinPoint.getArgs() == null) {
            return null;
        }

        Object result = null;
        LogDto logDto = new LogDto();
        UserDto dto = (UserDto) joinPoint.getArgs()[0];

        User entity = userDao.findById(dto.getId());

        logDto.setCreateBy(userLoginName);
        logDto.setCreateTime(new Date());
        logDto.setOperation(LogUtil.UPDATE.getCode());
        StringBuffer msg = new StringBuffer().append(getLogCell(ApplicationModule.MODULE_SYSTEM));
        msg.append(getLogCell("Update User"));

        msg.append(getLogCell(",", "LoginName: " + entity.getLoginName()));
        logDto.setContent(msg.toString());

        try {
            result = joinPoint.proceed();

            logDto.setResult(LogUtil.SUCCESS.getCode());

        } catch (Exception ex) {
            logDto.setResult(LogUtil.FAILURE.getCode());
            throw new ApplicationException(ex.getMessage());
        } finally {
            logService.log(logDto);
        }

        return result;
    }

    @Around(value = "resetPasswordCall()")
    public Object resetPasswordService(ProceedingJoinPoint joinPoint) throws Throwable {
        String userLoginName = securityService.getCurrentUserLoginName();

        if (userLoginName == null || joinPoint.getArgs() == null) {
            return null;
        }

        Object result = null;
        LogDto logDto = new LogDto();
        String id = (String) joinPoint.getArgs()[0];

        User entity = userDao.findById(new Long(id));

        logDto.setCreateBy(userLoginName);
        logDto.setCreateTime(new Date());
        logDto.setOperation(LogUtil.UPDATE.getCode());
        StringBuffer msg = new StringBuffer().append(getLogCell(ApplicationModule.MODULE_SYSTEM));
        msg.append(getLogCell("Reset Password"));

        msg.append(getLogCell(",", "LoginName: " + entity.getLoginName()));
        logDto.setContent(msg.toString());

        try {
            result = joinPoint.proceed();

            logDto.setResult(LogUtil.SUCCESS.getCode());

        } catch (Exception ex) {
            logDto.setResult(LogUtil.FAILURE.getCode());
            throw new ApplicationException(ex.getMessage());
        } finally {
            logService.log(logDto);
        }

        return result;
    }



    @Around(value = "deleteUserCall()")
    public Object deleteUserService(ProceedingJoinPoint joinPoint) throws Throwable {
        String userLoginName = securityService.getCurrentUserLoginName();

        Object result = null;
        String id = (String) joinPoint.getArgs()[0];
        User entity = null;
        if (id != null) {
            entity = userDao.findById(new Long(id));
        }

        StringBuffer msg = new StringBuffer();
        msg.append(getLogCell(ApplicationModule.MODULE_SYSTEM));
        msg.append(getLogCell("Delete User"));

        LogDto logDto = new LogDto();
        logDto.setCreateBy(userLoginName);
        logDto.setCreateTime(new Date());
        logDto.setOperation(LogUtil.DELETE.getCode());
        logDto.setResult(LogUtil.SUCCESS.getCode());
        msg.append(getLogCell(", ", "LoginName: " + entity.getLoginName()));
        logDto.setContent(msg.toString());

        try {
            result = joinPoint.proceed();
            logDto.setResult(LogUtil.SUCCESS.getCode());

        } catch (Exception ex) {
            logDto.setResult(LogUtil.FAILURE.getCode());
            throw new ApplicationException(ex.getMessage());
        } finally {
            logService.log(logDto);
        }

        return result;
    }

    @Around(value = "saveRoleCall()")
    public Object saveRoleService(ProceedingJoinPoint joinPoint) throws Throwable {
        String userLoginName = securityService.getCurrentUserLoginName();

        if (userLoginName == null || joinPoint.getArgs() == null) {
            return null;
        }

        Object result = null;
        LogDto logDto = new LogDto();
        RoleDto dto = (RoleDto) joinPoint.getArgs()[0];
        logDto.setCreateBy(userLoginName);
        logDto.setCreateTime(new Date());
        logDto.setOperation(LogUtil.INSERT.getCode());
        StringBuffer msg = new StringBuffer().append(getLogCell(ApplicationModule.MODULE_SYSTEM));
        msg.append(getLogCell("New Role"));

        if (dto != null) {
            msg.append(getLogCell(",", "Name: " + dto.getName()));
            logDto.setContent(msg.toString());
        }

        try {
            result = joinPoint.proceed();
            logDto.setResult(LogUtil.SUCCESS.getCode());
        } catch (Exception ex) {
            logDto.setResult(LogUtil.FAILURE.getCode());
            throw new ApplicationException(ex.getMessage());
        } finally {
            logService.log(logDto);
        }

        return result;
    }

    @Around(value = "updateRoleCall()")
    public Object updateRoleService(ProceedingJoinPoint joinPoint) throws Throwable {
        String userLoginName = securityService.getCurrentUserLoginName();

        if (userLoginName == null || joinPoint.getArgs() == null) {
            return null;
        }

        Object result = null;
        LogDto logDto = new LogDto();
        RoleDto dto = (RoleDto) joinPoint.getArgs()[0];

        Role entity = roleDao.findById(dto.getId());

        logDto.setCreateBy(userLoginName);
        logDto.setCreateTime(new Date());
        logDto.setOperation(LogUtil.UPDATE.getCode());
        StringBuffer msg = new StringBuffer().append(getLogCell(ApplicationModule.MODULE_SYSTEM));
        msg.append(getLogCell("Update Role"));

        msg.append(getLogCell(",", "Name: " + entity.getName()));
        logDto.setContent(msg.toString());

        try {
            result = joinPoint.proceed();

            logDto.setResult(LogUtil.SUCCESS.getCode());
        } catch (Exception ex) {
            logDto.setResult(LogUtil.FAILURE.getCode());
            throw new ApplicationException(ex.getMessage());
        } finally {
            logService.log(logDto);
        }

        return result;
    }

    @Around(value = "deleteRoleCall()")
    public Object deleteRoleService(ProceedingJoinPoint joinPoint) throws Throwable {
        String userLoginName = securityService.getCurrentUserLoginName();

        Object result = null;

        String id = (String) joinPoint.getArgs()[0];

        Role entity = null;
        if (id != null) {
            entity = roleDao.findById(new Long(id));
        }

        StringBuffer msg = new StringBuffer();
        msg.append(getLogCell(ApplicationModule.MODULE_SYSTEM));
        msg.append(getLogCell("Delete Role"));

        LogDto logDto = new LogDto();
        logDto.setCreateBy(userLoginName);
        logDto.setCreateTime(new Date());
        logDto.setOperation(LogUtil.DELETE.getCode());

        msg.append(getLogCell(", ", "Name: " + entity.getName()));
        logDto.setContent(msg.toString());

        try {
            result = joinPoint.proceed();

            logDto.setResult(LogUtil.SUCCESS.getCode());
        } catch (Exception ex) {
            logDto.setResult(LogUtil.FAILURE.getCode());
            throw new ApplicationException(ex.getMessage());
        } finally {
            logService.log(logDto);
        }
        return result;
    }


    @Around(value = "assignRolesForPermissionCall()")
    public Object assignRolesForPermissionService(ProceedingJoinPoint joinPoint) throws Throwable {
        String userLoginName = securityService.getCurrentUserLoginName();

        Object[] args = joinPoint.getArgs();
        Object result = null;

        String resourceId = (String) args[0];
        List<String> roleIds = (List<String>) args[1];

        Resource resource = permissionDao.findById(new Long(resourceId));

        StringBuffer msg = new StringBuffer();
        msg.append(getLogCell(ApplicationModule.MODULE_SYSTEM));
        msg.append(getLogCell("Assign Role For Permission"));

        LogDto logDto = new LogDto();
        logDto.setCreateBy(userLoginName);
        logDto.setCreateTime(new Date());
        logDto.setOperation(LogUtil.UPDATE.getCode());

        String roles = "";
        if (resource != null) {
            for (String id : roleIds) {
                Role role = roleDao.findById(new Long(id));
                if (role != null) {
                    roles += role.getName() + ",";
                }
            }
            roles = roles.substring(0, roles.lastIndexOf(","));
        }
        msg.append(getLogCell(", ", "Permission: " + resource.getName(), "Roles: " + roles));
        logDto.setContent(msg.toString());

        try {
            result = joinPoint.proceed();

            logDto.setResult(LogUtil.SUCCESS.getCode());
        } catch (Exception ex) {
            logDto.setResult(LogUtil.FAILURE.getCode());
            throw new ApplicationException(ex.getMessage());
        } finally {
            logService.log(logDto);
        }
        return result;
    }

    @Around(value = "deleteRoleForPermissionCall()")
    public Object deleteRoleFromPermissionService(ProceedingJoinPoint joinPoint) throws Throwable {
        String userLoginName = securityService.getCurrentUserLoginName();

        Object[] args = joinPoint.getArgs();

        String permissionId = (String) args[0];
        String roleId = (String) args[1];

        Resource resource = permissionDao.findById(new Long(permissionId));

        StringBuffer msg = new StringBuffer();
        msg.append(getLogCell(ApplicationModule.MODULE_SYSTEM));
        msg.append(getLogCell("Remove Role For Permission"));

        LogDto logDto = new LogDto();
        logDto.setCreateBy(userLoginName);
        logDto.setCreateTime(new Date());
        logDto.setOperation(LogUtil.UPDATE.getCode());
        String roles = "";
        if (resource != null) {
            Role role = roleDao.findById(new Long(roleId));
            if (role != null) {
                roles += role.getName() + ",";
            }
            roles = roles.substring(0, roles.lastIndexOf(","));
        }

        msg.append(getLogCell(", ", "Permission: " + resource.getName(), "Roles: " + roles));
        logDto.setContent(msg.toString());

        Object result = null;

        try {
            result = joinPoint.proceed();
            logDto.setResult(LogUtil.SUCCESS.getCode());
        } catch (Exception ex) {
            logger.error(ex.getMessage());
            logDto.setResult(LogUtil.FAILURE.getCode());
            throw new ApplicationException(ex.getMessage());
        } finally {
            logService.log(logDto);
        }

        return result;
    }

    @Around(value = "assignRolesForUserCall()")
    public void assignRolesForUserService(ProceedingJoinPoint joinPoint) throws Throwable {
        String userLoginName = securityService.getCurrentUserLoginName();

        Object[] args = joinPoint.getArgs();

        String userId = (String) args[0];
        List<String> roleIds = (List<String>) args[1];

        User user = userDao.findById(new Long(userId));

        StringBuffer msg = new StringBuffer();
        msg.append(getLogCell(ApplicationModule.MODULE_SYSTEM));
        msg.append(getLogCell("Assign Role to User"));

        LogDto logDto = new LogDto();
        logDto.setCreateBy(userLoginName);
        logDto.setCreateTime(new Date());
        logDto.setOperation(LogUtil.UPDATE.getCode());
        String roles = "";

        if (user != null) {

            for (String id : roleIds) {
                Role role = roleDao.findById(new Long(id));
                if (role != null) {
                    roles += role.getName() + ",";
                }
            }
            roles = roles.substring(0, roles.lastIndexOf(","));
        }
        msg.append(getLogCell(", ", "User: " + user.getLoginName(), "Roles: " + roles));
        logDto.setContent(msg.toString());

        Object result = null;
        try {

            result = joinPoint.proceed();

            logDto.setResult(LogUtil.SUCCESS.getCode());

        } catch (Exception ex) {
            logDto.setResult(LogUtil.FAILURE.getCode());
            throw new ApplicationException(ex.getMessage());
        } finally {
            logService.log(logDto);
        }
    }


    @Around(value = "deleteRolesForUserCall()")
    public void deleteRolesForUserService(ProceedingJoinPoint joinPoint) throws Throwable {
        //Get the logined user name.
        String userLoginName = securityService.getCurrentUserLoginName();

        Object[] args = joinPoint.getArgs();

        //get the content of option
        String userId = (String) args[0];
        List<String> roleIds = (List<String>) args[1];

        User user = userDao.findById(new Long(userId));

        StringBuffer msg = new StringBuffer();
        msg.append(getLogCell(ApplicationModule.MODULE_SYSTEM));
        msg.append(getLogCell("Remove Role from User"));

        LogDto logDto = new LogDto();
        logDto.setCreateBy(userLoginName);
        logDto.setCreateTime(new Date());
        logDto.setOperation(LogUtil.UPDATE.getCode());

        String roles = "";
        if (user != null) {
            for (String id : roleIds) {
                Role role = roleDao.findById(new Long(id));
                if (role != null) {
                    roles += role.getName() + ",";
                }
            }
            roles = roles.substring(0, roles.lastIndexOf(","));
//            msg.append(getLogCell(roles));
        }
        msg.append(getLogCell(", ", "User: " + user.getLoginName(), "Roles: " + roles));
        logDto.setContent(msg.toString());

        Object result = null;

        try {
            result = joinPoint.proceed();

            logDto.setResult(LogUtil.SUCCESS.getCode());
        } catch (Exception ex) {
            logger.error(ex.getMessage());
            logDto.setResult(LogUtil.FAILURE.getCode());
            throw new ApplicationException(ex.getMessage());
        } finally {
            logService.log(logDto);
        }
    }

    //@Around(value = "importDataFromCvsCall()")
    public void importDataFromCvsService(ProceedingJoinPoint joinPoint) throws Throwable {
        //Get the logined user name.
        String userLoginName = securityService.getCurrentUserLoginName();

        Object[] args = joinPoint.getArgs();

        //get the content of option
        String filePath = (String) args[0];
        String projectId = (String) args[1];
        Long fileSize = (Long) args[2];
        String fileName = filePath.substring(filePath.lastIndexOf(ApplicationUtil.getFileSeparator()) + 1);

        Project project = projectDao.findById(new Long(projectId));

        StringBuffer msg = new StringBuffer();
        msg.append(getLogCell(ApplicationModule.MODULE_DATA_IMPORT));
        msg.append(getLogCell("Data Import"));

        LogDto logDto = new LogDto();
        logDto.setCreateBy(userLoginName);
        logDto.setCreateTime(new Date());
        logDto.setOperation(LogUtil.INSERT.getCode());
        msg.append(getLogCell(",", "Project: " + project.getName(), "File: " + fileName, "FileSize: " + fileSize));
        logDto.setContent(msg.toString());


        Object result = null;
        try {
            result = joinPoint.proceed();
            logDto.setResult(LogUtil.SUCCESS.getCode());
        } catch (Exception ex) {
            logDto.setResult(LogUtil.FAILURE.getCode());
            throw new ApplicationException(ex.getMessage());
        } finally {
            logService.log(logDto);
        }
    }

    @Around(value = "logicDeleteTestFileCall()")
    public void logicDeleteTestFileService(ProceedingJoinPoint joinPoint) throws Throwable {
        String userLoginName = securityService.getCurrentUserLoginName();

        Object[] args = joinPoint.getArgs();

        String fileId = (String) args[0];

        TestFile file = testFileDao.findByTestFileUUID(fileId);

        StringBuffer msg = new StringBuffer();
        msg.append(getLogCell(ApplicationModule.MODULE_DATA_IMPORT));
        msg.append(getLogCell("Delete File"));

        LogDto logDto = new LogDto();
        logDto.setCreateBy(userLoginName);
        logDto.setCreateTime(new Date());
        logDto.setOperation(LogUtil.DELETE.getCode());

        msg.append(getLogCell(", ", "Project : " + file.getProject().getName(), "File: " + file.getOriginalName()));
        logDto.setContent(msg.toString());

        Object result = null;

        try {
            result = joinPoint.proceed();

            logDto.setResult(LogUtil.SUCCESS.getCode());
        } catch (Exception ex) {
            logger.error(ex.getMessage());
            logDto.setResult(LogUtil.FAILURE.getCode());
            throw new ApplicationException(ex.getMessage());
        } finally {
            logService.log(logDto);
        }
    }

    @Around(value = "deleteTestFileCall()")
    public void deleteTestFileService(ProceedingJoinPoint joinPoint) throws Throwable {
        String userLoginName = securityService.getCurrentUserLoginName();

        Object[] args = joinPoint.getArgs();

        String fileId = (String) args[0];

        TestFile file = testFileDao.findByTestFileUUID(fileId);

        StringBuffer msg = new StringBuffer();
        msg.append(getLogCell(ApplicationModule.MODULE_DATA_IMPORT));
        msg.append(getLogCell("Destroy File"));

        LogDto logDto = new LogDto();
        logDto.setCreateBy(userLoginName);
        logDto.setCreateTime(new Date());
        logDto.setOperation(LogUtil.DELETE.getCode());

        msg.append(getLogCell(", ", "Project : " + file.getProject().getName(), "File: " + file.getOriginalName()));
        logDto.setContent(msg.toString());

        Object result = null;

        try {
            result = joinPoint.proceed();

            logDto.setResult(LogUtil.SUCCESS.getCode());
        } catch (Exception ex) {
            logger.error(ex.getMessage());
            logDto.setResult(LogUtil.FAILURE.getCode());
            throw new ApplicationException(ex.getMessage());
        } finally {
            logService.log(logDto);
        }
    }

    @Around(value = "restoreTestFileCall()")
    public void restoreTestFileService(ProceedingJoinPoint joinPoint) throws Throwable {
        String userLoginName = securityService.getCurrentUserLoginName();

        Object[] args = joinPoint.getArgs();

        String fileId = (String) args[0];

        TestFile file = testFileDao.findByTestFileUUID(fileId);

        StringBuffer msg = new StringBuffer();
        msg.append(getLogCell(ApplicationModule.MODULE_DATA_IMPORT));
        msg.append(getLogCell("Restore File"));

        LogDto logDto = new LogDto();
        logDto.setCreateBy(userLoginName);
        logDto.setCreateTime(new Date());
        logDto.setOperation(LogUtil.UPDATE.getCode());

        msg.append(getLogCell(", ", "Project : " + file.getProject().getName(), "File: " + file.getOriginalName()));
        logDto.setContent(msg.toString());

        Object result = null;

        try {
            result = joinPoint.proceed();

            logDto.setResult(LogUtil.SUCCESS.getCode());
        } catch (Exception ex) {
            logger.error(ex.getMessage());
            logDto.setResult(LogUtil.FAILURE.getCode());
            throw new ApplicationException(ex.getMessage());
        } finally {
            logService.log(logDto);
        }
    }


    @Around(value = "saveEmailCall()")
    public void saveEmailService(ProceedingJoinPoint joinPoint) throws Throwable {
        String userLoginName = securityService.getCurrentUserLoginName();

        if (userLoginName == null || joinPoint.getArgs() == null) {
            return;
        }

        Object[] args = joinPoint.getArgs();

        MailConfiguration dto = (MailConfiguration) args[0];

        StringBuffer msg = new StringBuffer();
        msg.append(getLogCell(ApplicationModule.MODULE_SYSTEM));
        msg.append(getLogCell("New Email"));

        LogDto logDto = new LogDto();
        logDto.setCreateBy(userLoginName);
        logDto.setCreateTime(new Date());
        logDto.setOperation(LogUtil.UPDATE.getCode());

        msg.append(getLogCell(",", "Name: " + dto.getName()));
        logDto.setContent(msg.toString());

        try {
            joinPoint.proceed();
            logDto.setResult(LogUtil.SUCCESS.getCode());

        } catch (Exception ex) {
            logger.error(ex.getMessage());
            logDto.setResult(LogUtil.FAILURE.getCode());
            throw new ApplicationException(ex.getMessage());
        } finally {
            logService.log(logDto);
        }
    }

    @Around(value = "updateEmailCall()")
    public void updateEmailService(ProceedingJoinPoint joinPoint) throws Throwable {
        //Get the logined user name.
        String userLoginName = securityService.getCurrentUserLoginName();

        if (userLoginName == null || joinPoint.getArgs() == null) {
            return;
        }

        Object[] args = joinPoint.getArgs();

        MailConfiguration dto = (MailConfiguration) args[0];

        Email email = emailDao.findById(new Long(dto.getId()));

        StringBuffer msg = new StringBuffer();
        msg.append(getLogCell(ApplicationModule.MODULE_SYSTEM));
        msg.append(getLogCell("Update Email"));

        LogDto logDto = new LogDto();
        logDto.setCreateBy(userLoginName);
        logDto.setCreateTime(new Date());
        logDto.setOperation(LogUtil.UPDATE.getCode());

        msg.append(getLogCell(",", "Name: " + email.getName()));
        logDto.setContent(msg.toString());

        try {
            joinPoint.proceed();
            logDto.setResult(LogUtil.SUCCESS.getCode());

        } catch (Exception ex) {
            logger.error(ex.getMessage());
            logDto.setResult(LogUtil.FAILURE.getCode());
            throw new ApplicationException(ex.getMessage());
        } finally {
            logService.log(logDto);
        }
    }

    @Around(value = "deleteEmailCall()")
    public void deleteEmailService(ProceedingJoinPoint joinPoint) throws Throwable {
        //Get the logined user name.
        String userLoginName = securityService.getCurrentUserLoginName();

        if (userLoginName == null || joinPoint.getArgs() == null) {
            return;
        }

        Object[] args = joinPoint.getArgs();

        String id = (String) args[0];

        Email email = emailDao.findById(new Long(id));

        StringBuffer msg = new StringBuffer();
        msg.append(getLogCell(ApplicationModule.MODULE_SYSTEM));
        msg.append(getLogCell("Delete Email"));

        LogDto logDto = new LogDto();
        logDto.setCreateBy(userLoginName);
        logDto.setCreateTime(new Date());
        logDto.setOperation(LogUtil.DELETE.getCode());

        msg.append(getLogCell(",", "Name: " + email.getName()));
        logDto.setContent(msg.toString());

        try {
            joinPoint.proceed();
            logDto.setResult(LogUtil.SUCCESS.getCode());

        } catch (Exception ex) {
            logger.error(ex.getMessage());
            logDto.setResult(LogUtil.FAILURE.getCode());
            throw new ApplicationException(ex.getMessage());
        } finally {
            logService.log(logDto);
        }
    }


    @Around(value = "updateEmailStatusCall()")
    public void updateEmailStatusService(ProceedingJoinPoint joinPoint) throws Throwable {
        //Get the logined user name.
        String userLoginName = securityService.getCurrentUserLoginName();

        if (userLoginName == null) {
            //None logined user
            return;
        }

        //check the arguments
        if (joinPoint.getArgs() == null) {//None args
            return;
        }
        Object[] args = joinPoint.getArgs();

        //get the content of option
        String emailId = (String) args[0];
        EmailStatus status = (EmailStatus) args[1];

        Email email = emailDao.findById(new Long(emailId));
        StringBuffer msg = new StringBuffer();
        msg.append(getLogCell(ApplicationModule.MODULE_SYSTEM));
        msg.append(getLogCell("Update Email Status"));

        LogDto logDto = new LogDto();
        logDto.setCreateBy(userLoginName);
        logDto.setCreateTime(new Date());
        logDto.setOperation(LogUtil.UPDATE.getCode());

        msg.append(getLogCell(",", "Name: " + email.getName(), "Status: " + status.toString()));
        logDto.setContent(msg.toString());

        try {
            joinPoint.proceed();
            logDto.setResult(LogUtil.SUCCESS.getCode());

        } catch (Exception ex) {
            logger.error(ex.getMessage());
            logDto.setResult(LogUtil.FAILURE.getCode());
            throw new ApplicationException(ex.getMessage());
        } finally {
            logService.log(logDto);
        }
    }


    @Around(value = "updateSystemAlarmRuleCPWRCall()")
    public void updateSystemAlarmRuleCPWRService(ProceedingJoinPoint joinPoint) throws Throwable {
        //Get the logined user name.
        String userLoginName = securityService.getCurrentUserLoginName();

        if (userLoginName == null || joinPoint.getArgs() == null) {
            return;
        }

        Object[] args = joinPoint.getArgs();
        DataDictionaryDto dto = (DataDictionaryDto) args[0];

        StringBuffer msg = new StringBuffer();
        msg.append(getLogCell(ApplicationModule.MODULE_SYSTEM));
        msg.append(getLogCell("Update CP Warning Rule"));

        LogDto logDto = new LogDto();
        logDto.setCreateBy(userLoginName);
        logDto.setCreateTime(new Date());
        logDto.setOperation(LogUtil.UPDATE.getCode());

        String attrName = dto.getAttributeName();

        if ("goodBoundaryValue".equalsIgnoreCase(attrName)) {
            attrName = "Well";
        } else if ("excellentBoundaryValue".equalsIgnoreCase(attrName)) {
            attrName = "Excellence";
        } else if ("acceptableBoundaryValue".equalsIgnoreCase(attrName)) {
            attrName = "Accept";
        } else if ("rectificationBoundaryValue".equalsIgnoreCase(attrName)) {
            attrName = "Rectification";
        }
        String pName = "";
        List<DataDictionary> entitys = dataDictionaryDao.findByAttributeNameAndParentId("indiceName", dto.getId());
        if (entitys != null && !entitys.isEmpty()) {
            pName = entitys.get(0).getAttributeValue();
        }

        msg.append(getLogCell(", ", "Name: " + pName, "Param: " + attrName, "Value: " + dto.getAttributeValue()));
        logDto.setContent(msg.toString());

        try {
            joinPoint.proceed();
            logDto.setResult(LogUtil.SUCCESS.getCode());

        } catch (Exception ex) {
            logger.error(ex.getMessage());
            logDto.setResult(LogUtil.FAILURE.getCode());
            throw new ApplicationException(ex.getMessage());
        } finally {
            logService.log(logDto);
        }
    }


    @Around(value = "updateSystemAlarmRuleCCWR()")
    public void updateSystemAlarmRuleCCWRCall(ProceedingJoinPoint joinPoint) throws Throwable {
        //Get the logined user name.
        String userLoginName = securityService.getCurrentUserLoginName();

        if (userLoginName == null || joinPoint.getArgs() == null) {
            return;
        }
        Object[] args = joinPoint.getArgs();
        DataDictionaryDto dto = (DataDictionaryDto) args[0];

        StringBuffer msg = new StringBuffer();
        msg.append(getLogCell(ApplicationModule.MODULE_SYSTEM));
        msg.append(getLogCell("Update CC Warning Rule"));

        LogDto logDto = new LogDto();
        logDto.setCreateBy(userLoginName);
        logDto.setCreateTime(new Date());
        logDto.setOperation(LogUtil.UPDATE.getCode());

        String attrName = dto.getAttributeName();

        if ("points".equalsIgnoreCase(attrName)) {
            attrName = "Param1";
        } else if ("somePoints".equalsIgnoreCase(attrName)) {
            attrName = "Param2";
        }

        String pName = "";
        List<DataDictionary> entitys = dataDictionaryDao.findByAttributeNameAndParentId("code", dto.getId());
        if (entitys != null && !entitys.isEmpty()) {
            pName = entitys.get(0).getAttributeValue();
        }

        msg.append(getLogCell(",", "Name: " + pName, "Param: " + attrName, "Value: " + dto.getAttributeValue()));
        logDto.setContent(msg.toString());

        try {
            joinPoint.proceed();
            logDto.setResult(LogUtil.SUCCESS.getCode());

        } catch (Exception ex) {
            logger.error(ex.getMessage());
            logDto.setResult(LogUtil.FAILURE.getCode());
            throw new ApplicationException(ex.getMessage());
        } finally {
            logService.log(logDto);
        }
    }


    /**
     * Using the java reflection to get the args value of aspected method (save, update)
     * paste the args to the operation content
     */
    private String optionContent(Object[] args, String mName) throws Exception {
        if (args == null) {
            return null;
        }

        StringBuffer rs = new StringBuffer();
        rs.append(mName);
        rs.append(" [");
        for (Object info : args) {
            // get all method of object
            Method[] methods = info.getClass().getDeclaredMethods();

            // loop in methods, check the get methods
            for (Method method : methods) {

                String methodName = method.getName();
                // if get
                if (methodName.indexOf("get") == -1) {// not get
                    continue;// do nothing
                }

                if (methodName.indexOf("Name") == -1) {// not getName
                    continue;// do nothing
                }

                Object rsValue = null;
                try {
                    // invoke the get method
                    rsValue = method.invoke(info);
                    if (rsValue == null) {//none value
                        continue;
                    }
                } catch (Exception e) {
                    continue;
                }
                //put value to content
                String vName = methodName.substring(3, methodName.length());
                rs.append(vName + ": " + rsValue + ",");
            }
        }
        String result = rs.toString();
        if (result.lastIndexOf(",") != -1) {
            result = result.substring(0, result.lastIndexOf(","));
        }

        result += "]";
        return result;
    }


    private String getLogCell(String content) {
        return "[" + content + "]";
    }

    private String getLogCell(String sp, String... contents) {
        StringBuffer msg = new StringBuffer();
        msg.append("[");
        if (sp != null) {
            for (String s : contents) {
                msg.append(s).append(sp);
            }
        }
        msg.deleteCharAt(msg.lastIndexOf(sp));
        msg.append("]");
        return msg.toString();
    }
}
